const fs = require('fs');
const path = require('path');
var tools = require('../../../libs/tools');
var config = require(tools.rootPath + 'config');
var { connection, pool, model } = require(tools.rootPath + 'libs/model');

const Auth = require(tools.controllerPath + 'common/auth');
const functions = require(tools.appPath + 'functions');

const copyFile = tools.promisify(fs.copyFile, fs); // 通过 promisify 方法把 copyFile 方法包装成 Promise 接口
module.exports = class extends Auth {

    async __before() {
        const flag = await super.__before();
        if (flag === false) return false;

        this.assign({
            UPLOAD_URL1: `/${this.MM}/upload_img_action`,
            UPLOAD_URL2: `/${this.MM}/upload_file_action`,
            UPLOAD_URL3: `/${this.MM}/upload_img_tradition_action`,
            UPLOAD_URL4: `/${this.MM}/upload_file_tradition_action`,
            UPLOAD_HUGE: `/${this.MM}/upload_huge_action`,
        });

        return true;
    }

    async upload_file_common(extensions) {
        /*
        {
            "name":"ma01.jpg",
            "data":{"type":"Buffer","data":[]},
            "size":768420,
            "encoding":"7bit",
            "tempFilePath":"D:\\tmp\\tmp-1-1586834146916",
            "truncated":false,
            "mimetype":"image/jpeg",
            "md5":"d70e4c45a4ffb1aea17b1441c13a9a05"
        }
        */

        let post = this.post();
        if (tools.isEmpty(post)) {
            return this.msg(0);
        }
        var { class: cls, i, callback, uniq } = post;
        //主要判断文件大小和类型
        let file = this.req.files.file;
        if (!file) {
            return this.json({ result: { 'code': 100, 'msg': 'file is empty', 'url': '', 'class': cls, 'i': i, 'callback': callback } });
        }
        //判断文件大小
        let size = file.size;
        if (size > 2 * 1024 * 1024) {
            return this.json({ result: { 'code': 101, 'msg': '文件超出最大大小', 'url': '', 'class': cls, 'i': i, 'callback': callback } });
        }
        //判断文件后缀
        let filename = file.name;
        let ext = functions.extension(filename);
        if (!functions.in_array(ext, extensions)) {
            return this.json({ result: { 'code': 102, 'msg': '文件类型不正确', 'url': '', 'class': cls, 'i': i, 'callback': callback } });
        }
        //创建文件夹
        let destination = tools.rootPath + 'public/uploads/' + functions.date('', 'Y/M/D') + '/' + functions.date('', 'YMDhms') + functions.randomNum(100000, 999999) + '.' + ext;
        if (!fs.existsSync(path.dirname(destination))) {
            fs.mkdirSync(path.dirname(destination), { recursive: true });
        }
        //console.log(destination);
        //cross-device link not permitted
        let url = destination.replace(tools.rootPath + 'public', '');
        await copyFile(file.tempFilePath, destination);
        if (!fs.existsSync(destination)) {
            return this.json({ result: { 'code': 103, 'msg': '文件写入失败', 'url': '', 'class': cls, 'i': i, 'callback': callback } });
        }
        //save to db
        let c = await this.action(this.MM);
        if (tools.isFunction(c._save_attachment)) {
            await c._save_attachment(0, uniq, url);
        }
        return this.json({ result: { code: 0, msg: 'success', url: url, class: cls, i: i, callback: callback } });
    }

    async upload_img() {
        let get = this.get();
        var { class: cls, i, callback, uniq } = get;
        if (!cls || typeof (i) == 'undefined' || !callback || !uniq) {
            this.msg(0, 'lose class/i/callback/uniq');
            return;
        }
        this.assign({
            cls, i, callback, uniq,
        });
        return this.tpl('upload/upload_img');
    }

    async upload_img_action() {
        let extensions = [
            'jpg',
            'png',
            'gif',
        ];
        return await this.upload_file_common(extensions);
    }

    async upload_file() {
        let get = this.get();
        var { class: cls, i, callback, uniq } = get;
        if (!cls || typeof (i) == 'undefined' || !callback || !uniq) {
            this.msg(0, 'lose class/i/callback/uniq');
            return;
        }
        this.assign({
            cls, i, callback, uniq,
        });
        return this.tpl('upload/upload_file');
    }

    async upload_file_action() {
        let extensions = [
            'jpg',
            'png',
            'gif',
            'rar',
            'zip',
            'pdf',
            'txt',
            'doc',
            'docx',
            'ppt',
            'pptx',
            'xls',
            'xlsx',
            'swf',
        ];
        return await this.upload_file_common(extensions);
    }

    async mkhtml(fn, fileurl, message) {
        let str = `<script type="text/javascript">window.parent.CKEDITOR.tools.callFunction(${fn}, '${fileurl}', '${message}');</script>`;
        return str;
    }

    async ck_common(extensions) {
        // /article/upload_ck_img?uniq=cc9b52ca-0153-44ce-aa23-7adfcd5570b8&CKEditor=content&CKEditorFuncNum=1&langCode=zh-cn
        let post = this.post();
        if (tools.isEmpty(post)) {
            return this.msg(0);
        }
        let get = this.get();
        var { uniq, CKEditorFuncNum } = get;
        if (tools.isEmpty(CKEditorFuncNum)) {
            return this.msg(0, '错误的功能调用请求！');
        }

        if (tools.isEmpty(uniq)) {
            return this.mkhtml(CKEditorFuncNum, '', 'lose uniq!');
        }

        //主要判断文件大小和类型
        let file = this.req.files.upload;
        if (!file) {
            return this.mkhtml(CKEditorFuncNum, '', 'file is empty');
        }
        //判断文件大小
        let size = file.size;
        if (size > 2 * 1024 * 1024) {
            return this.mkhtml(CKEditorFuncNum, '', '文件超出最大大小');
        }
        //判断文件后缀
        let filename = file.name;
        let ext = functions.extension(filename);
        if (!functions.in_array(ext, extensions)) {
            return this.mkhtml(CKEditorFuncNum, '', '文件类型不正确');
        }
        //创建文件夹
        let destination = tools.rootPath + 'public/uploads/' + functions.date('', 'Y/M/D') + '/' + functions.date('', 'YMDhms') + functions.randomNum(100000, 999999) + '.' + ext;
        if (!fs.existsSync(path.dirname(destination))) {
            fs.mkdirSync(path.dirname(destination), { recursive: true });
        }
        //console.log(destination);
        //cross-device link not permitted
        let url = destination.replace(tools.rootPath + 'public', '');
        await copyFile(file.tempFilePath, destination);
        if (!fs.existsSync(destination)) {
            return this.mkhtml(CKEditorFuncNum, '', '文件写入失败');
        }
        //save to db
        let c = await this.action(this.MM);
        if (tools.isFunction(c._save_attachment)) {
            await c._save_attachment(0, uniq, url);
        }

        return this.mkhtml(CKEditorFuncNum, url, '上传成功！');
    }

    async upload_ck_img() {
        let extensions = [
            'jpg',
            'png',
            'gif',
        ];
        return await this.ck_common(extensions);
    }

    async upload_ck_file() {
        let extensions = [
            'jpg',
            'png',
            'gif',
            'rar',
            'zip',
            'pdf',
            'txt',
            'doc',
            'docx',
            'ppt',
            'pptx',
            'xls',
            'xlsx',
            'swf',
        ];
        return await this.ck_common(extensions);
    }

    async upload_huge() {
        let get = this.get();
        var { class: cls, i, callback, uniq } = get;
        if (!cls || typeof (i) == 'undefined' || !callback || !uniq) {
            this.msg(0, 'lose class/i/callback/uniq');
            return;
        }
        this.assign({
            cls, i, callback, uniq,
        });
        return this.tpl('upload/upload_huge');
    }

    async upload_huge_action() {
        let post = this.post();
        if (tools.isEmpty(post)) {
            return this.msg(0);
        }
        var { name, total, index, fileSize, class: cls, i, callback, uniq } = post;
        //主要判断文件大小和类型
        let file = this.req.files.data;
        if (!file) {
            return this.json({ result: { 'code': 100, 'msg': 'file is empty', 'url': '', 'class': cls, 'i': i, 'callback': callback } });
        }
        //判断文件大小 最大2GB
        let size = fileSize;
        if (size > 2 * 1024 * 1024 * 1024) {
            return this.json({ result: { 'code': 101, 'msg': '文件超出最大大小', 'url': '', 'class': cls, 'i': i, 'callback': callback } });
        }
        //判断文件后缀
        let extensions = [
            'jpg',
            'png',
            'gif',
            'rar',
            'zip',
            'pdf',
            'txt',
            'doc',
            'docx',
            'ppt',
            'pptx',
            'xls',
            'xlsx',
            'swf',
            'iso',
        ];
        let filename = name;
        let ext = functions.extension(filename);
        if (!functions.in_array(ext, extensions)) {
            return this.json({ result: { 'code': 102, 'msg': '文件类型不正确', 'url': '', 'class': cls, 'i': i, 'callback': callback } });
        }
        //创建文件夹
        let DEST = await this.session('UPLOAD_HUGE_DEST');
        let destination;
        if (!tools.isEmpty(DEST)) {
            destination = DEST;
        } else {
            destination = tools.rootPath + 'public/uploads/' + functions.date('', 'Y/M/D') + '/' + functions.date('', 'YMDhms') + functions.randomNum(100000, 999999) + '.' + ext;
            await this.session('UPLOAD_HUGE_DEST', destination);
        }

        if (!fs.existsSync(path.dirname(destination))) {
            fs.mkdirSync(path.dirname(destination), { recursive: true });
        }
        //console.log(destination);
        //cross-device link not permitted
        let url = destination.replace(tools.rootPath + 'public', '');

        //如果第一次上传的时候，该文件已经存在，则删除文件重新上传
        if (index == 1 && fs.existsSync(destination) && fs.statSync(destination).size == fileSize) {
            fs.unlinkSync(destination);
        }

        //合并文件
        try {
            let d = fs.readFileSync(file.tempFilePath);
            fs.appendFileSync(destination, d);
        } catch (err) {
            return this.json({ result: { 'code': 103, 'msg': '文件写入失败', 'url': '', 'class': cls, 'i': i, 'callback': callback } });
        }

        //最后一块时
        if (index == total) {
            //save to db
            let c = await this.action(this.MM);
            if (tools.isFunction(c._save_attachment)) {
                await c._save_attachment(0, uniq, url);
            }

            this.session('UPLOAD_HUGE_DEST', null);
            return this.json({ result: { code: 0, msg: 'success', url: url, class: cls, i: i, callback: callback } });
        }
        //继续上传
        return this.json({ result: { code: 0, msg: 'success', url: '', class: cls, i: i, callback: callback } });
    }

    async upload_img_tradition() {
        let get = this.get();
        var { class: cls, i, callback, uniq } = get;
        if (!cls || typeof (i) == 'undefined' || !callback || !uniq) {
            this.msg(0, 'lose class/i/callback/uniq');
            return;
        }
        this.assign({
            cls, i, callback, uniq,
        });
        return this.tpl('upload/upload_img_tradition');
    }

    async upload_img_tradition_action() {
        let extensions = [
            'jpg',
            'png',
            'gif',
        ];
        return await this.upload_file_common(extensions);
    }

    async upload_file_tradition() {
        let get = this.get();
        var { class: cls, i, callback, uniq } = get;
        if (!cls || typeof (i) == 'undefined' || !callback || !uniq) {
            this.msg(0, 'lose class/i/callback/uniq');
            return;
        }
        this.assign({
            cls, i, callback, uniq,
        });
        return this.tpl('upload/upload_file_tradition');
    }

    async upload_file_tradition_action() {
        let extensions = [
            'jpg',
            'png',
            'gif',
            'rar',
            'zip',
            'pdf',
            'txt',
            'doc',
            'docx',
            'ppt',
            'pptx',
            'xls',
            'xlsx',
            'swf',
        ];
        return await this.upload_file_common(extensions);
    }
};